<?php
/**
 * @version		1.7
 * @package		TwitterTweet K2 Plugin (K2 plugin)
 * @author    Daniel Eliasson Stilero AB - http://www.stilero.com
 * @copyright	Copyright (c) 2011 Stilero AB. All rights reserved.
 * @license	GPLv2
* 	Joomla! is free software. This version may have been modified pursuant
* 	to the GNU General Public License, and as distributed it includes or
* 	is derivative of works licensed under the GNU General Public License or
* 	other free or open source software licenses.
 *
 *  This file is part of K2 TwitterTweet.

    K2 TwitterTweet is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BlogPing Pro is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with K2 TwitterTweet.  If not, see <http://www.gnu.org/licenses/>.
*/

// no direct access
defined('_JEXEC') or die ('Restricted access');

/**
 * Example K2 Plugin to render YouTube URLs entered in backend K2 forms to video players in the frontend.
 */

// Load the K2 Plugin API
JLoader::register('K2Plugin', JPATH_ADMINISTRATOR.DS.'components'.DS.'com_k2'.DS.'lib'.DS.'k2plugin.php');

class plgK2Twittertweet extends K2Plugin {
	var $k2Item;
	var $config;
        var $twitterFormToken;
        var $fullTweet;
        var $inBackend;
        var $errorOccured;
        const HTTP_STATUS_FOUND = '302';
        const HTTP_STATUS_OK = '200';

	function plgK2Twittertweet( & $subject, $params) {
		parent::__construct($subject, $params);
		$this->loadLanguage();
                $this->errorOccured = FALSE;
                $this->config = array(
                    'twitterLoginFormURL'   =>      'https://mobile.twitter.com/session/new',
                    'twitterLoginPostURL'   =>      'https://mobile.twitter.com/session',
                    'twitterDataURL'        =>      'https://mobile.twitter.com/',
                    'twitterUsername'       =>      $this->params->def('username'),
                    'twitterPassword'       =>      $this->params->def('password'),
                    'twitterWebAgent'       =>      'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
                    'twitterMaxHashTags'    =>      3,
                    'tinyURLAPI'            =>      'http://tinyurl.com/api-create.php?url=',
                    'curlPost'              =>      1,
                    'curlSSLVerifyPeer'     =>      false,
                    'curlSSLVerifyHost'     =>      2,
                    'curlCookieFile'        =>      '',
                    'curlReturnTransfer'    =>      1,
                    'curlFollowLocation'    =>      0
                );
	}

	public function onK2AfterDisplayContent( & $item, & $params, $limitstart) {
            $this->inBackend = false;
            $this->setK2Item($item);
            $this->tweet();
            return;
        }
	
	public function onAfterK2Save( &$item, $isNew ) {
            $this->inBackend = true;
            $this->prepareTables();
            $this->setK2Item($item);
            $this->tweet();
            return;
	}

        public function tweet() {
            if($this->isReadyToTweet()){
                $this->buildTweet();
                $this->setTwitterLoginFormToken();
                $this->twitterLogin();
                $this->sendMessageToTwitter();
            }
            if( ! $this->errorOccured ){
                $this->saveTweetToDB();
                $this->displayMessage("Tweeted: ".urldecode($this->fullTweet));
                return true;
            }
        }
 
        private function prepareTables() {
            if( $this->isJoomla15() ) {
                if( ! $this->tableExists() ){
                    $this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_NOTABLES"));
                    if( $this->createTables() ){
                        $this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_CREATEDTABLES"));
                    }else{
                        $this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_TABLESFAILED"), 'error');
                        $this->errorOccured = TRUE;
                        return FALSE;
                    }
                }
            }
        }      
        
	private function setTwitterLoginFormToken() {
            $twitterLoginFormPage = $this->getTwitterLoginFormPage();
            $arrayWithTheTokenInTheMiddle = explode("authenticity_token\" type=\"hidden\" value=\"", $twitterLoginFormPage);
            $arrayWithTheTokenInTheBeginning = explode("\"", $arrayWithTheTokenInTheMiddle[1]);
            $twitterLoginFormToken = $arrayWithTheTokenInTheBeginning[0];
            $this->twitterFormToken = $twitterLoginFormToken;
	}

        private function prepareToTweet() {
            $this->isServerSupportingRequiredFunctions();
            $this->createCookieFile();
            $this->isLoginDetailsEntered();
            $this->isItemActive();
            $this->isItemPublished();
            $this->isItemNewEnough();
            $this->isItemPublic();
            $this->isCategoryToTweet();
            $this->isTweetingToEarly();
            $this->isItemAlreadyTweeted();
        }
        
        private function isServerSupportingRequiredFunctions(){
            if($this->errorOccured){
                return FALSE;
            }
            if( !function_exists( curl_init ) || !function_exists(file_get_contents) ){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_NO_CURL_SUPPORT'), 'error');
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isLoginDetailsEntered() {
            if($this->errorOccured){
                return FALSE;
            }
            $twitterusername = $this->params->def('username');
            $twitterpassword = $this->params->def('password');
            if( $twitterusername == "" || $twitterpassword == ""){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_NOLOGINDETAILS'), 'error');
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isItemActive() {
            if($this->errorOccured){
                return FALSE;
            }
            if (($this->k2Item->published != 1)){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_NOTACTIVE'));
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isItemPublished() {
            if($this->errorOccured){
                return FALSE;
            }
            $date =& JFactory::getDate();
            $currentDate = $date->toMySQL();
            $itemPublishDate = $this->k2Item->pubplish_up;
            if ( $itemPublishDate > $currentDate ){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_NOTACTIVE'));
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isItemNewEnough() {
            if($this->errorOccured){
                return FALSE;
            }
            $postItemsNewerThanDate = $this->params->def('items_newer_than');
            $itemPublishDate = $this->k2Item->publish_up;
            if( ( $itemPublishDate < $postItemsNewerThanDate) && $postItemsNewerThanDate !="" ){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_ITEM_OLD'));
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isJoomla15() {
            if(version_compare(JVERSION,'1.5.0','ge')) {
                return TRUE;
            }
            return FALSE;
        }

        private function isJoomla16() {
            if(version_compare(JVERSION,'1.6.0','ge')) {
                return TRUE;
            }
            return FALSE;
        }

        private function isJoomla17() {
            if(version_compare(JVERSION,'1.7.0','ge')) {
                return TRUE;
            }
            return FALSE;
        }
        private function isItemPublic() {
            if($this->errorOccured){
                return FALSE;
            }
            $publicAccessCode = ($this->isJoomla15())?0:1;
            if( $this->k2Item->access != $publicAccessCode ){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_RESTRICT'));
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isCategoryToTweet() {
            if($this->errorOccured){
                return FALSE;
            }
            $categToPostArray = explode(",", $this->params->def('section_id'));
            $numberOfCategToPost = count($categToPostArray);
            $itemCategID = $this->k2Item->catid;
            if ( $this->params->def('section_id') == "" ){
                return TRUE;
            }
            if ( !in_array( $itemCategID, $categToPostArray ) ){
                $this->displayMessage(JText::_('PLG_CONTENT_K2_TWITTERTWEET_NOTSECTION'));
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isCookeFileSet() {
            if($this->config['curlCookieFile']){
                return TRUE;
            }else{
                $this->errorOccured = TRUE;
                return FALSE;
            }
        }

        private function isTweetingToEarly(){
            if($this->errorOccured){
                return FALSE;
            }
            $delayInMinutes = ( !is_numeric($this->params->def('delay')) || $this->params->def('delay')<2 )?3:$this->params->def('delay');
            $currentDate=date("Y-m-d H:i:s");
            $query;
            $db		= &JFactory::getDbo();
            if( $this->isJoomla16() || $this->isJoomla17() ) {
                $query	= $db->getQuery(true);
                $query->select('id');
                $query->from('#__k2_twittertweet_tweeted');
                $query->where("date > SUBTIME('".$currentDate."','0 0:".$delayInMinutes.":0.0')");
            }  elseif($this->isJoomla15()) {
                $query = "SELECT "
                    .$db->nameQuote('id').
                    " FROM ".$db->nameQuote('#__k2_twittertweet_tweeted').
                    " WHERE date > SUBTIME('".$currentDate."','0 0:".$delayInMinutes.":0.0')";
            }
            $db->setQuery($query);
            $postMadeWithinDelayTime = $db->loadObject();
            if($postMadeWithinDelayTime){
                $this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_DELAYED"));
                $this->errorOccured = TRUE;
                return TRUE;
            }
            return FALSE;
	}

        private function isItemAlreadyTweeted(){
            if($this->errorOccured){
                return FALSE;
            }
            $query;
            $db		= &JFactory::getDbo();
            $k2itemID = $this->k2Item->id;
            if($this->isJoomla16() || $this->isJoomla17()) {
                $query	= $db->getQuery(true);
                $query->select('id');
                $query->from('#__k2_twittertweet_tweeted');
                $query->where('article_id=' . $db->Quote($k2itemID));
            }  elseif($this->isJoomla15() ) {
                $sectionCat = $article->sectionid;
                $query = 'SELECT '
                .$db->nameQuote('id').
                    ' FROM '.$db->nameQuote('#__k2_twittertweet_tweeted').
                    ' WHERE '.$db->nameQuote('article_id').'='.$db->Quote($k2itemID);
            }
            $db->setQuery($query);
            $itemAlreadyPosted = $db->loadObject();
            if($itemAlreadyPosted){
                $this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_ALREADY_TWEETED"));
                $this->errorOccured = TRUE;
                return TRUE;
            }
            return FALSE;
	}

        private function isReadyToTweet() {
            $this->prepareToTweet();
            if($this->errorOccured){
                return FALSE;
            }else{
                return TRUE;
            }
        }

	public function displayMessage($msg, $messageType = "") {
            $isSetToDisplayMessages = ($this->params->def('pingmessages')==0)?false:true;
            if( ! $isSetToDisplayMessages || ! $this->inBackend ){
                return;
            }else{
                JFactory::getApplication()->enqueueMessage( $msg, $messageType);
            }
	}
 
        private function getTwitterLoginFormPage() {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL,               $this->config['twitterLoginFormURL']); 		
            curl_setopt($ch, CURLOPT_USERAGENT,         $this->config['twitterWebAgent']); 
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,    $this->config['curlReturnTransfer']); 
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,    $this->config['curlFollowLocation']);
            curl_setopt($ch, CURLOPT_COOKIEFILE,        $this->config['curlCookieFile']);
            curl_setopt($ch, CURLOPT_COOKIEJAR,         $this->config['curlCookieFile']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,    $this->config['curlSSLVerifyHost']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,    $this->config['curlSSLVerifyPeer']);
            $twitterLoginFormPage = curl_exec ($ch);	
            curl_close ($ch);
            return $twitterLoginFormPage;
        }

        private function twitterLogin() {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL,               $this->config['twitterLoginPostURL']);
            curl_setopt($ch, CURLOPT_USERAGENT,         $this->config['twitterWebAgent']);
            curl_setopt($ch, CURLOPT_POST,              $this->config['curlPost']);
            curl_setopt($ch, CURLOPT_POSTFIELDS,        $this->getTwitterLoginPostfieldsHTTPQuery()); //Build a query from the postarray
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,    $this->config['curlReturnTransfer']);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,    $this->config['curlFollowLocation']);
            curl_setopt($ch, CURLOPT_REFERER,           $this->config['twitterLoginFormURL']);		//set a spoof referrer
            curl_setopt($ch, CURLOPT_COOKIEFILE,        $this->config['curlCookieFile']);
            curl_setopt($ch, CURLOPT_COOKIEJAR,         $this->config['curlCookieFile']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,    $this->config['curlSSLVerifyHost']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,    $this->config['curlSSLVerifyPeer']);
            $twitterLoginResults = curl_exec ($ch);
            $twitterLoginResultsArray = curl_getinfo($ch);
            if( $twitterLoginResultsArray['http_code'] != self::HTTP_STATUS_FOUND ){
		$this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_LOGIN_FAILED").$twitterLoginResultsArray['http_code'], "error");
		curl_close ($ch);
                return FALSE;
            }
            curl_close ($ch);
            return TRUE;
            
        }

        private function createCookieFile() {
            if($this->errorOccured){
                return FALSE;
            }
            $cookieFileCreated = tempnam(DS."tmp", "cookies");
            if (!$cookieFileCreated){
                $this->displayMessage(JText::_('Could not create file to store sessions, check your directory permissions.'), 'error');
                $this->errorOccured = TRUE;
                return FALSE;
            }
            $this->config['curlCookieFile'] = $cookieFileCreated;
        }

        private function getTwitterLoginPostfieldsHTTPQuery() {
            $twitterLoginPostFieldsArray = array(
                'username'	=>  $this->config['twitterUsername'],
                'password'  =>  $this->config['twitterPassword']
            );
            $twitterLoginHTTPQuery = http_build_query($twitterLoginPostFieldsArray);
            return $twitterLoginHTTPQuery;           
        }

        private function getTweetPostfieldsHTTPQuery() {
            $tweetPostFieldsArray = array(
                'tweet[text]'           =>  $this->fullTweet,
                'authenticity_token'    =>  $this->twitterFormToken
            );
            $tweetPostHTTPQuery = http_build_query($tweetPostFieldsArray);
            return $tweetPostHTTPQuery;           
        }

        private function sendMessageToTwitter() {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL,               $this->config['twitterDataURL']);
            curl_setopt($ch, CURLOPT_USERAGENT,         $this->config['twitterWebAgent']);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,    $this->config['curlReturnTransfer']);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,    $this->config['curlFollowLocation']);
            curl_setopt($ch, CURLOPT_REFERER,           $this->config['twitterLoginFormURL']);
            curl_setopt($ch, CURLOPT_COOKIEFILE,        $this->config['curlCookieFile']);
            curl_setopt($ch, CURLOPT_COOKIEJAR,         $this->config['curlCookieFile']);
            curl_setopt($ch, CURLOPT_POST,              $this->config['curlPost']);
            curl_setopt($ch, CURLOPT_POSTFIELDS,        $this->getTweetPostfieldsHTTPQuery());
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,    $this->config['curlSSLVerifyHost']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,    $this->config['curlSSLVerifyPeer']);
            $result = curl_exec ($ch);
            $tweetPostResultsArray = curl_getinfo($ch);
            curl_close ($ch);
            //Kill the cookie, we don't need it anymore
            unlink($this->config['curlCookieFile']);
            switch ($tweetPostResultsArray['http_code']) {
                case self::HTTP_STATUS_OK:
                    return true;
                    break;
                case self::HTTP_STATUS_FOUND:
                    return true;
                    break;
                default:
                    $this->displayMessage(JText::_("PLG_CONTENT_K2_TWITTERTWEET_TWEET_FAILED").$tweetPostResultsArray['http_code'], 'error');
                    break;
            }
            return false;
        }

        private function getFullURL() {
            $urlQuery = "?option=com_k2&view=item&id=".$this->k2Item->id;
            $fullURL = JURI::root()."index.php".$urlQuery;
            return $fullURL;
        }

        private function getTinyURL() {
            $fullURL = $this->getFullURL();
            $encodedFullURL = urlencode($fullURL);
            $apiCallForTinyURL = $this->config['tinyURLAPI'].$encodedFullURL;
            
            $tinyURL = @file_get_contents($apiCallForTinyURL);
            if($tinyURL == ""){
                $tinyURL = $this->getTinyUrlUsinCurl();
            }
            $tinyUrlLength = strlen($tinyURL);
            $fullUrlLength = strlen($fullURL);
            if( ($fullUrlLength < $tinyUrlLength ) || $tinyURL == "" ){
                $tinyURL = $fullURL;
            }
            return $tinyURL;
        }
        
        private function getTinyUrlUsinCurl() {
            $fullURL = $this->getFullURL();
            $apiCallForTinyURL = $this->config['tinyURLAPI'] . $fullURL;
            $postvars = array('url' => $fullURL );
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL,               $apiCallForTinyURL); 	 //The auth page to visit
            curl_setopt($ch, CURLOPT_POST,              $this->config['curlPost']);
            curl_setopt($ch, CURLOPT_POSTFIELDS,        http_build_query($postvars)); //Build a query from the postarray
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,    $this->config['curlReturnTransfer']);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,    $this->config['curlFollowLocation']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,    $this->config['curlSSLVerifyHost']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,    $this->config['curlSSLVerifyPeer']);
            $tinyURL = curl_exec ($ch);							//Go get the page and put the result in a variable
            $resultArray = curl_getinfo($ch);
            curl_close ($ch);
            switch ($resultArray['http_code']) {
                case self::HTTP_STATUS_OK:
                    return $tinyURL;
                    break;
                case self::HTTP_STATUS_FOUND:
                    return $tinyURL;
                    break;
                default:
                    $this->displayMessage(JText::_("Errorcode:").$resultArray['http_code'], 'error');
                    break;
            }
            return false;
	}

        private function getK2ItemTags() {
		$query;
		$db = &JFactory::getDbo();
		if( $this->isJoomla16() || $this->isJoomla17()) {
                    $query = $db->getQuery(true);
                    $query->select('name');
                    $query->from('#__k2_tags AS t');
                    $query->innerJoin('#__k2_tags_xref AS x ON x.tagID = t.id');
                    $query->where('x.itemID = '.(int) $this->k2Item->id);
		}  elseif( $this->isJoomla15() ) {
                    $query = "SELECT ".$db->nameQuote('name').
                        " FROM ".$db->nameQuote('#__k2_tags')." AS t".
                        " INNER JOIN " . $db->nameQuote('#__k2_tags_xref')." AS x".
                        " ON  x.tagID = t.id".
                        " WHERE x.itemID = " . $db->Quote($this->k2Item->id);
		}
		$db->setQuery($query);
		$k2ItemTags = $db->loadObjectList();
		return $k2ItemTags;
	}

        private function getHashTags() {
            $k2ItemTagsArray = $this->getK2ItemTags();         
            if(count($k2ItemTagsArray) == 0){
            	return;
            }
            $tagsArray;
            $i = 0;
            foreach ($k2ItemTagsArray as $key => $value) {
                if($i++ < $this->config['twitterMaxHashTags'] ){
                    $tagsArray[] = str_replace(" ", "", $value->name) ;
                }
            }
            $tagsArray = ( count($tagsArray) > 0 )? implode(",",$tagsArray):"";
            $metakeys = str_replace(" ", "", $tagsArray);
            $hashtags = explode(",", $metakeys);
            $implodedtags = ( count($hashtags) >0 )? implode(" #", $hashtags):"";
            $hashtags = (count($hashtags) >0)?" #".$implodedtags:"";
            return $hashtags;
	}

        private function buildTweet() {
            $tinyURL = $this->getTinyURL();
            $fullTextMessage = $this->k2Item->title;
            $hashTagsCommaSeparated = $this->getHashTags();
            $tinyURLLength = count($tinyURL);
            $hashTagsLength = count($hashTagsCommaSeparated);
            $truncatedTweet = substr($fullTextMessage, 0, 140 - $tinyURLLength -1 - $hashTagsLength -1);
            $fullTweet = $truncatedTweet." ".$tinyURL.$hashTagsCommaSeparated;
            $this->fullTweet = $fullTweet;
        }
	
	private function createTables() {
		$dbObject		=& JFactory::getDbo();
		$queryDropTable = "DROP TABLE IF EXISTS `#__k2_twittertweet_tweeted`";
		$queryCreateTable = "CREATE TABLE `#__k2_twittertweet_tweeted` (
  			`id` int(11) NOT NULL auto_increment,
  			`article_id` int(11) NOT NULL default 0,
  			`cat_id` int(11) NOT NULL default 0,
  			`articlelink` varchar(255) NOT NULL default '',
  			`date` datetime NOT NULL default '0000-00-00 00:00:00',
  			`language` char(7) NOT NULL default '',
  			PRIMARY KEY  (`id`)
			) DEFAULT CHARSET=utf8;";
		$dbObject->setQuery($queryDropTable);
		$resultDropTable = $dbObject->query();
		$dbObject->setQuery($queryCreateTable);
		$resultCreateTable = $dbObject->query();
		if($resultCreateTable){
                    return TRUE;
		}
		return FALSE;
	}
	
        private function saveTweetToDB() {
            $itemID = $this->k2Item->id;
            $itemCategID = $this->k2Item->catid;
            $itemLink = $this->k2Item->link;
            $itemLanguage = $this->k2Item->language;
            $date=&JFactory::getDate();
            $data =new stdClass();
            $data->id = null;
            $data->article_id = $itemID;
            $data->cat_id = $itemCategID;
            $data->articlelink = $itemLink;
            $data->date = date("Y-m-d H:i:s");
            $data->language = $itemLanguage;
            $db = &JFactory::getDbo();
            $db->insertObject('#__k2_twittertweet_tweeted', $data, id);
            return;
        }

	private function tableExists() {
		$dbObject		=& JFactory::getDbo();
		$query = "DESC `#__k2_twittertweet_tweeted`";
		$dbObject->setQuery($query);
		$tableFound = $dbObject->query();
		if($tableFound){
                    return TRUE;
		}
		return FALSE;
	}
	
	private function setK2Item($item) {
		$this->k2Item = $item;
	}
} // END K2 CLASS
